﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using log4net;
using NHibernate;
using NHibernate.Criterion;
using TeamCommunitySolution.Domain.DataLayer.Venues;
using TeamCommunitySolution.Repositories.Base;
using TeamCommunitySolution.Repositories.Providers;

namespace TeamCommunitySolution.Repositories.Venues
{
    /// <summary>
    /// Venue Repository Implementation.
    /// </summary>
    public class VenueRepositoryImpl : VenueRepository
    {
        /// <summary>
        /// The log instance.
        /// </summary>
        private static readonly ILog _log = LogManager.GetLogger(typeof(VenueRepository));

        /// <summary>
        /// Creates the instance.
        /// </summary>
        /// <returns>A venue repository instance.</returns>
        public static VenueRepository CreateInstance()
        {
            return new VenueRepositoryImpl();
        }

        /// <summary>
        /// Saves the venue.
        /// </summary>
        /// <param name="venue">The venue.</param>
        public void SaveVenue(Venue venue)
        {
            using (ISession session = Nhibernate.Factory.OpenSession())
            {
                var scope = session.BeginTransaction();
                try
                {
                    session.SaveOrUpdate(venue);
                    scope.Commit();
                }
                catch (SqlException ex)
                {
                    scope.Rollback();
                    string message = "Unable to save object [Venue] in the datastore";
                    this.HandleException(message, ex);
                }
            }
        }

        public Venue GetVenueByField(string fieldName, string fieldValue)
        {
            using (ISession session = Nhibernate.Factory.OpenSession())
            {
                ICriteria crit = session.CreateCriteria(typeof(Venue));
                crit.Add(Expression.Eq(fieldName, fieldValue));

                IList<Venue> results = crit.List<Venue>();

                if (results.Count > 1)
                {
                    throw new BaseRepositoryException(string.Format("Duplicate objects [Venue] found in the datastore. Field: {0}, Value: {1}", fieldName, fieldValue));
                }

                if (results.Count == 0)
                {
                    return null;
                }

                return results[0];
            }
        }

        /// <summary>
        /// Deletes the venue.
        /// </summary>
        /// <param name="venue">The venue.</param>
        public void DeleteVenue(Venue venue)
        {
            using (ISession session = Nhibernate.Factory.OpenSession())
            {
                var scope = session.BeginTransaction();
                try
                {
                    session.Delete(venue);
                    scope.Commit();
                }
                catch (SqlException ex)
                {
                    scope.Rollback();
                    string message = "Unable to remove object [Venue] in the datastore";
                    this.HandleException(message, ex);
                }
            }
        }

        /// <summary>
        /// Handles the exception.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The exception.</param>
        private void HandleException(string message, Exception ex)
        {
            _log.Error(message, ex);
            throw new VenueRepositoryException(message, ex);
        }
    }
}
